package com.fp.m7.client.presenter;

import net.customware.gwt.presenter.client.EventBus;
import net.customware.gwt.presenter.client.place.PlaceRequest;
import net.customware.gwt.presenter.client.place.PlaceRequestEvent;
import net.customware.gwt.presenter.client.widget.WidgetDisplay;
import net.customware.gwt.presenter.client.widget.WidgetPresenter;

import com.allen_sauer.gwt.log.client.Log;
import com.fp.m7.client.AccountContext;
import com.fp.m7.client.MyMessages;
import com.fp.m7.client.common.IValidatableDisplay;
import com.fp.m7.client.common.ProfileTab;
import com.fp.m7.client.event.InfoEvent;
import com.fp.m7.client.event.InfoEvent.UserMessageType;
import com.fp.m7.client.place.ProfilePlace;
import com.fp.m7.shared.ValidationResult;
import com.fp.m7.shared.services.CommentServiceAsync;
import com.fp.m7.shared.validator.CommentValidator;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasText;
import com.google.inject.Inject;

/**
 * New Comment Presenter is designed to handle the action of posting a new comment.
 * 
 * @author 7
 */
public class NewCommentPresenter extends WidgetPresenter<NewCommentPresenter.Display> {

    public interface Display extends WidgetDisplay, IValidatableDisplay {

        void setContents(String avatarUrl);

        HasClickHandlers getProfileButton();

        HasClickHandlers getSubmitButton();

        HasText getContents();

        void clear();

    }

    private static MyMessages msg = GWT.create(MyMessages.class);

    private AccountContext accountContext;
    private CommentServiceAsync commentService;
    private CommentValidator validator;

    @Inject
    public NewCommentPresenter(Display display, EventBus eventBus, //
            AccountContext accountContext, //
            CommentValidator validator, //
            CommentServiceAsync commentService) {

        super(display, eventBus);

        this.accountContext = accountContext;
        this.validator = validator;
        this.commentService = commentService;
    }

    @Override
    protected void onBind() {
        display.getSubmitButton().addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent evt) {
                String content = display.getContents().getText();
                ValidationResult result = validator.validate(content);
                if (!result.isOk()) {
                    display.showErrors(result);
                } else {
                    postComment(content);
                }
            }
        });
        display.getProfileButton().addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent evt) {
                PlaceRequest req = new PlaceRequest(ProfilePlace.NAME);
                eventBus.fireEvent(new PlaceRequestEvent(req));
            }
        });
    }

    @Override
    protected void onUnbind() {
    }

    @Override
    protected void onRevealDisplay() {
        display.clear();

        if (accountContext.getAuthenticatedAccount() != null) {
            display.setContents(accountContext.getAuthenticatedAccount().getUserDto().getAvatarUrl());
        }
    }

    private void postComment(String content) {
        commentService.postComment(content, new AsyncCallback<Boolean>() {
            @Override
            public void onSuccess(Boolean value) {
                if (Boolean.TRUE.equals(value)) {
                    eventBus.fireEvent(new InfoEvent(msg.messagePosted(), UserMessageType.SUCCESS));

                    PlaceRequest req = new PlaceRequest(ProfilePlace.NAME) //
                            .with(ProfilePlace.TAB, ProfileTab.COMMENTS.toString());
                    eventBus.fireEvent(new PlaceRequestEvent(req));

                    display.clear();
                } else {
                    error();
                }
            }

            @Override
            public void onFailure(Throwable arg0) {
                Log.info("Posting a comment failed");
                error();
            }
        });
    }

    private void error() {
        eventBus.fireEvent(new InfoEvent(msg.errorWhilePostingComment(), UserMessageType.WARNING));
    }

}
